package com.ml4ai.backend.security.config;

import com.ml4ai.backend.security.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
import org.springframework.session.web.http.HeaderHttpSessionStrategy;
import org.springframework.session.web.http.HttpSessionStrategy;

/**
 * Created by uesr on 2018/9/8.
 */
@EnableSpringHttpSession
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${security.authURL}")
    private String authInformationSource;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    SecurityLoginFailureHandler securityLoginFailureHandler;

    @Autowired
    SecurityLoginSuccessHandler securityLoginSuccessHandler;

    @Autowired
    PasswordEncoder passwordEncoder;

    @Autowired
    SecurityAuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    SecurityAccessDeniedHandler securityAccessDeniedHandler;

    @Autowired
    SecurityAuthencationFilter securityAuthencationFilter;

    @Autowired
    SecurityRequestFilter securityRequestFilter;

    @Autowired
    CrossWrapperFilter crossWrapperFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests().antMatchers("/configuration/ui").permitAll();
        http.authorizeRequests().antMatchers("/configuration/security").permitAll();
        http.authorizeRequests().antMatchers("/v2/api-docs").permitAll();
        http.authorizeRequests().antMatchers("/swagger-resources").permitAll();
        http.authorizeRequests().antMatchers("/swagger-ui.html").permitAll();
        http.authorizeRequests().antMatchers("/webjars/**").permitAll();
        http.authorizeRequests().antMatchers("/api/stream/**").permitAll();
        http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
        http.exceptionHandling().accessDeniedHandler(securityAccessDeniedHandler);
        http.csrf().disable();
        http.authorizeRequests().antMatchers(authInformationSource).permitAll();
        http.authorizeRequests().anyRequest().authenticated();
        http.addFilterBefore(securityAuthencationFilter, FilterSecurityInterceptor.class);
        http.addFilterBefore(securityRequestFilter, UsernamePasswordAuthenticationFilter.class);
        http.addFilterBefore(crossWrapperFilter, SecurityAuthencationFilter.class);
        //http.userDetailsService(userDetailsService);
        http.
                formLogin().
                successHandler(securityLoginSuccessHandler).
                failureHandler(securityLoginFailureHandler).
                usernameParameter("username").
                passwordParameter("password").
                loginProcessingUrl(authInformationSource).
                permitAll();
    }

    //@Autowired
    //CrossWrapperFilter crossWrapperFilter;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
        super.configure(auth);
    }

    @Bean
    public SecurityRequestFilter securityRequestFilter() {
        return new SecurityRequestFilter();
    }

    @Bean
    public PasswordEncoder getPasswordEncoderBean() {
        return new PasswordEncoder() {
            @Override
            public String encode(CharSequence charSequence) {
                return charSequence.toString();
            }

            @Override
            public boolean matches(CharSequence charSequence, String s) {
                return charSequence.toString().equals(s);
            }
        };
    }

    @Bean
    public HttpSessionStrategy pushHttpSessionStrategy() throws Exception {
        HttpSessionStrategy webSessionStrategy;
        HeaderHttpSessionStrategy basedHeaderHttpSessionStrategy = new HeaderHttpSessionStrategy();
        basedHeaderHttpSessionStrategy.setHeaderName("X-AUTH-TOKEN");
        webSessionStrategy = basedHeaderHttpSessionStrategy;
        return webSessionStrategy;
    }

}
